package com.selftaught.login.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.selftaught.login.common.ErrorCode;
import com.selftaught.login.constant.UserConstant;
import com.selftaught.login.exception.BusinessException;
import com.selftaught.login.mapper.UserMapper;
import com.selftaught.login.model.dto.user.UserLoginRequest;
import com.selftaught.login.model.dto.user.UserRegisterRequest;
import com.selftaught.login.model.entity.User;
import com.selftaught.login.model.vo.UserVO;
import com.selftaught.login.service.UserService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import javax.servlet.http.HttpServletRequest;

/**
 * 用户服务实现
 *
 * @author <a href="https://gitee.com/wanghuya">程序员虎牙</a>
 * @date 2024-09-26
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    /**
     * 注册
     *
     * @param userRegisterRequest userRegisterRequest
     * @return 结果
     */
    @Override
    public long register(UserRegisterRequest userRegisterRequest) {
        // 校验
        if (ObjectUtil.isNull(userRegisterRequest)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        String userAccount = userRegisterRequest.getUserAccount();
        String userPassword = userRegisterRequest.getUserPassword();
        String checkUserPassword = userRegisterRequest.getCheckUserPassword();
        if (StrUtil.isAllBlank(userAccount, userPassword, checkUserPassword)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        if (userAccount.length() < 4) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户账号过短");
        }
        if (userPassword.length() < 8) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户密码过短");
        }
        if (!userPassword.equals(checkUserPassword)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "两次输入的密码不一致");
        }
        // 安全操作
        synchronized (userAccount.intern()) {
            // 账号 userAccount 唯一
            QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
            userQueryWrapper.eq(User.USER_ACCOUNT, userAccount);
            long count = this.count(userQueryWrapper);
            if (count > 0) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "账号已存在");
            }
            // 加密
            String encryptPassword = DigestUtils.md5DigestAsHex((UserConstant.SALT + userPassword).getBytes());
            // 入库
            User user = new User();
            user.setUserAccount(userAccount);
            user.setUserPassword(encryptPassword);
            boolean save = this.save(user);
            if (!save) {
                throw new BusinessException(ErrorCode.SYSTEM_ERROR, "注册失败");
            }
            return user.getId();
        }
    }

    /**
     * 登录
     *
     * @param userLoginRequest userLoginRequest
     * @param request          request
     * @return 结果
     */
    @Override
    public User login(UserLoginRequest userLoginRequest, HttpServletRequest request) {
        // 校验
        if (ObjectUtil.isNull(userLoginRequest)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        String userAccount = userLoginRequest.getUserAccount();
        String userPassword = userLoginRequest.getUserPassword();
        if (StrUtil.isAllBlank(userAccount, userPassword)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        if (userAccount.length() < 4) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "账号错误");
        }
        if (userPassword.length() < 8) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "密码错误");
        }
        // 查询用户是否存在
        String encryptPassword = DigestUtils.md5DigestAsHex((UserConstant.SALT + userPassword).getBytes());
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.eq(User.USER_ACCOUNT, userAccount);
        userQueryWrapper.eq(User.USER_PASSWORD, encryptPassword);
        User user = this.getOne(userQueryWrapper);
        // 用户不存在
        if (ObjectUtil.isNull(user)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "账号或密码错误");
        }
        // 记录用户的登录态
        request.getSession().setAttribute(UserConstant.USER_LOGIN_STATUS, user);
        return user;
    }

    /**
     * 退出登录
     *
     * @param request request
     * @return 结果
     */
    @Override
    public boolean logout(HttpServletRequest request) {
        // 校验
        if (ObjectUtil.isNull(request)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        if (ObjectUtil.isNull(request.getSession().getAttribute(UserConstant.USER_LOGIN_STATUS))) {
            throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR);
        }
        // 移除登录态
        request.getSession().removeAttribute(UserConstant.USER_LOGIN_STATUS);
        return true;
    }

    /**
     * 获取当前登录用户
     *
     * @param request request
     * @return 结果
     */
    @Override
    public User getLoginUser(HttpServletRequest request) {
        Object userObj = request.getSession().getAttribute(UserConstant.USER_LOGIN_STATUS);
        User currentUser = (User) userObj;
        if (ObjectUtil.isNull(currentUser) || ObjectUtil.isNull(currentUser.getId())) {
            throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR);
        }
        currentUser = getById(currentUser.getId());
        if (ObjectUtil.isNull(currentUser)) {
            throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR);
        }
        return currentUser;
    }

    /**
     * 获取脱敏的用户信息 集合
     *
     * @param user user
     * @return 结果
     */
    @Override
    public UserVO getUserVo(User user) {
        if (ObjectUtil.isNull(user)) {
            return null;
        }
        UserVO userVO = new UserVO();
        BeanUtils.copyProperties(user, userVO);
        return userVO;
    }
}
